package com.ztesoft.report.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ztesoft.report.base.pojo.R;
import com.ztesoft.report.base.service.impl.BaseServiceImpl;
import com.ztesoft.report.dao.ReportCategoryDao;
import com.ztesoft.report.dao.ReportUserRoleDao;
import com.ztesoft.report.dao.ServiceInterfaceDao;
import com.ztesoft.report.entity.Report;
import com.ztesoft.report.entity.ReportCategory;
import com.ztesoft.report.entity.ReportCategoryDto;
import com.ztesoft.report.entity.ServiceInterface;
import com.ztesoft.report.exception.RException;
import com.ztesoft.report.service.ReportCategoryService;
import com.ztesoft.report.service.ServiceInterfaceService;
import com.ztesoft.report.service.UserService;
import com.ztesoft.report.utils.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 报表类别表 服务实现类
 * </p>
 *
 * @author y3tu
 * @since 2018-05-29
 */
@Service
public class ReportCategoryServiceImpl extends BaseServiceImpl<ReportCategoryDao, ReportCategory> implements ReportCategoryService {
    @Autowired
    ReportCategoryDao reportCategoryDao;
    @Autowired
    ServiceInterfaceDao serviceInterfaceDao;
    @Autowired
    ServiceInterfaceService serviceInterfaceService;
    @Autowired
    ReportCategoryService reportCategoryService;
    @Autowired
    ReportUserRoleDao reportUserRoleDao;
    @Autowired
    private UserService userService;

    private static Map<String, Object> cacheMap = new HashMap<String, Object>();

    @Override
    public Map getTreeList(int type) {
        //刷新缓存
        if (type == 1) {
            getAllTreeNodes(0);
        }
        if (cacheMap.get(0+"") != null) {
            return R.ok(cacheMap.get(0+""));
        }
        //获取所有根节点
        List<ReportCategoryDto> treeNodes = getAllTreeNodes(0);
        return R.ok(treeNodes);
    }

    @Override
    @Transactional
    public Map addTreeNode(ReportCategory reportCategory) {
        //判断是否有相同的名字，相同的父节点，状态为00A的节点
        int count = reportCategoryDao.countSameParentSameNameNode(reportCategory);
        if (count > 0) {
            throw  new RuntimeException();
        }
        reportCategory.setCreateTime(DateUtil.toDate(DateUtil.getDateTime(),"yyyyMMdd HH:mm:ss"));
        //修改父级的has_child为1
        reportCategoryDao.updateHasChildById(reportCategory);
        //新增一个子节点
        reportCategory.setStatus("00A");
        reportCategory.setHasChild(0);
        reportCategoryService.insert(reportCategory);
        //刷新缓存
        getAllTreeNodes(0);
        return R.ok();
    }

    @Override
    public Map delTreeNode(List<Integer> ids, String user) {
        ReportCategory reportCategory = new ReportCategory();
        reportCategory.setUpdateUser(user);
        reportCategory.setUpdateTime(DateUtil.toDate(DateUtil.getDateTime(),"yyyyMMdd HH:mm:ss"));
        for (Integer id : ids) {
            reportCategory.setId(id);
            reportCategoryDao.delTreeNode(reportCategory);
        }
        getAllTreeNodes(0);
        return R.ok();
    }

    @Override
    public Map updateTreeNode(ReportCategory reportCategory) {
        reportCategory.setUpdateTime(new Date());
        reportCategory.setId(reportCategory.getParentId());
        reportCategoryDao.updateTreeNode(reportCategory);
        getAllTreeNodes(0);
        return R.ok();
    }

    @Override
    public Map getReportList(Map param) {
        int size = (int) param.get("size");
        int current = (int) param.get("current");
        PageHelper.startPage(current, size);
        List<Report> list = null;
        if (param.get("categoryId") != null && !"".equals(param.get("categoryId"))) {
            List<Integer> ids = getAllChildId((Integer) param.get("categoryId"));
            param.put("categoryId", ids);
        } else {
            param.remove("categoryId");
        }
        String userId = param.get("userId").toString();
        //1是管理员直接走以前老逻辑，全量查询
        if (userId != null && "1".equals(userId)) {
            list = reportCategoryDao.getReportList(param);
        } else {
            list = reportCategoryDao.getReportList(param);
            List<String> roleids=userService.selectRoleIdByUserId(userId);
            //使用userid，查询出属于userid 的reportid
            List<Integer> reportIds = reportUserRoleDao.selectByUserId(userId);
            //使用roleids循环去查询属于roleid的reportid，然后添加进integerList
            roleids.forEach(e->{
                List<Integer> integerList1 = reportUserRoleDao.selectByRoleId(e);
                if (integerList1.size()>0){
                    CollUtil.addAllIfNotContains(reportIds,integerList1);
                }
            });
            Iterator<Report> iterator = list.iterator();
            //把list中不包含在reportIds中的remove掉
            while(iterator.hasNext()){
              boolean  contains = CollUtil.contains(reportIds,iterator.next().getId());
                if (!contains){
                    iterator.remove();
                }
            }
        }
        PageInfo<Report> page = new PageInfo<>(list);
        return R.ok(page);
    }

    @Override
    public Map test() {
        return R.ok(getAllChildId(775));
    }

    @Override
    @Transactional
    public Map publishReport(List<Map<String, Object>> param,boolean isPublishMerge) {
        if (isPublishMerge) {
            StringBuffer reportIds = new StringBuffer("");
            for (Map<String, Object> map : param) {
                Integer id = (Integer) map.get("id");
                String status = map.get("status").toString();
                if ("00X".equals(status)) {
                    throw new ArrayIndexOutOfBoundsException();
                }
                //判断是否有 数据没有处理完成
                int count = serviceInterfaceDao.getNoPassCount(id);
                if (count > 0) {
                    throw new NullPointerException();
                }
                reportIds.append(id+",");
            }
            ServiceInterface serviceInterface = new ServiceInterface();
            String ids = reportIds.substring(0,reportIds.length()-1);
            serviceInterface.setReportId(ids);
            serviceInterface.setName("合并发布:"+ids);
            serviceInterface.setStatus("00W");
            serviceInterfaceService.insert(serviceInterface);
        } else {
            for (Map<String, Object> map : param) {
                Integer id = (Integer) map.get("id");
                String status = map.get("status").toString();
                if ("00X".equals(status)) {
                    throw new ArrayIndexOutOfBoundsException();
                }
                //判断是否有 数据没有处理完成
                int count = serviceInterfaceDao.getNoPassCount(id);
                if (count > 0) {
                    throw new NullPointerException();
                }
                //初始化年月日，如果不传入账期，默认当前年月日
                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
                String yyyyMMdd = sdf.format(new Date());
                String year = yyyyMMdd.substring(0,4);
                String month = yyyyMMdd.substring(4,6);
                String day = yyyyMMdd.substring(6,8);
                ServiceInterface serviceInterface = new ServiceInterface();
                serviceInterface.setName(changeData(map.get("excelTitle").toString(),"",year,month,day));
                serviceInterface.setReportId(map.get("id").toString());
                serviceInterface.setStatus("00W");
                serviceInterfaceService.insert(serviceInterface);
            }
        }
        return R.ok();
    }


    /**
     * 替换一些字符串
     * @param oldData
     * @param newData
     * @param year
     * @param month
     * @param day
     * @return
     */
    public String changeData(String oldData,String newData,String year,String month,String day) {
        //理论上来说替换会一次全部替换完，如果出现不能替换的会出现死循环，所以count代表次数，如果一次没替换完，说明存在错误替换字符
        int count = 0;
        String nowTime = new SimpleDateFormat("yyyyMMdd").format(new Date());
        while (oldData.contains("#{{")) {
            if (count > 1) {
                throw new RException("存在错误的替换字符，不在#{{YYYY}}、#{{MM}}、#{{DD}}行列");
            }
            oldData = oldData.replace("#{{TITLE}}",newData);
            oldData = oldData.replace("#{{YYYY}}",year);
            oldData = oldData.replace("#{{MM}}",month);
            oldData = oldData.replace("#{{DD}}",day);
            oldData = oldData.replace("#{{YYYYMMDD}}",nowTime);
            count++;
        }
        return oldData;
    }

    @Override
    @Transactional
    public Map delReport(List<Map<String, Object>> param) {
        for (Map<String, Object> map : param) {
            Integer id = (Integer) map.get("id");
            //判断是否有 数据没有处理完成
            int count = serviceInterfaceDao.getNoPassCount(id);
            if (count > 0) {
                throw new NullPointerException();
            }
            map.put("createTime", new Date());
            reportCategoryDao.delReport(map);
        }
        return null;
    }

    private List<ReportCategoryDto> getAllTreeNodes(int parentId) {
        List<ReportCategoryDto> treeNodes = new ArrayList<ReportCategoryDto>();
        List<ReportCategory> nodes = reportCategoryDao.getNodeByParentId(parentId);
        for(ReportCategory node : nodes) {
            ReportCategoryDto reportCategoryDto = new ReportCategoryDto();
            reportCategoryDto.setId(node.getId());
            reportCategoryDto.setLabel(node.getName());
            reportCategoryDto.setSequence(node.getSeq());
            //如果还有子节点 最好不用has_child判断容易出问题拿id进去查即可
            int count = reportCategoryDao.countNodeByParentId(node.getId());
            if (count > 0) {
                reportCategoryDto.setChildren(getAllTreeNodes(node.getId()));
            }else {
                reportCategoryDto.setChildren(new ArrayList<ReportCategoryDto>());
            }
            treeNodes.add(reportCategoryDto);
        }
        cacheMap.put(parentId+"", treeNodes);
        return (List<ReportCategoryDto>) cacheMap.get(parentId+"");
    }

    @Cacheable(value = "node", key = "#parentId")
    public List<Integer> getAllChildId(int parentId) {
        List<Integer> allNode = new ArrayList<Integer>();
        allNode.add(parentId);
        List<ReportCategory> nodes = reportCategoryDao.getNodeByParentId(parentId);
        for(ReportCategory node : nodes) {
            //如果还有子节点 最好不用has_child判断容易出问题拿id进去查即可
            int count = reportCategoryDao.countNodeByParentId(node.getId());
            if (count > 0) {
                for (Integer id : getAllChildId(node.getId())) {
                    allNode.add(id);
                }
            }else {
                allNode.add(node.getId());
            }
        }
        return allNode;
    }

}
